/*
 * lock.c
 *
 */

#include "request.h"
#include "reply.h"
#include "lock.h"
#include "libdlm.h"
#include "log.h"

#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>

char filename_buff[FILENAME_MAX];

void dlmd_register(pid_t pid, char* filename)
{
	debug("request from %u: register resource: %s", pid, filename);
	int fd;
	struct process *proc;
	if ((proc = lock_ck_process(pid)) == NULL) {
        proc = lock_add_process(pid);
		info("new process, pid %u", pid);
    }
    fd = proc->fd;
	struct resource *res;
	struct stat st;
	stat(filename, &st);
	if ((res = lock_ck_resource_stat(&st)) == NULL) {
        res = lock_add_resource(&st);
		info("new resource %d", res->id);
	}
    lock_link_proc_res(proc, res);
	dlmd_reply_resource(fd, res->id);
	info("process pid: %d registered resource: %d", pid, res->id);
}
void dlmd_lock(pid_t pid, resource_id_t resource, lock_type_t lock, timeout_t timeout)
{
	debug2("request from %u: lock resource: %d type: %d timeout %l", pid, resource, lock, timeout);
	int fd;
	struct process *proc;
    if ((proc = lock_ck_process(pid)) == NULL) {
        proc = lock_add_process(pid);
        info("new process, pid %u", pid);
    }
    fd = proc->fd;
	struct resource *res;
	if ((res = lock_ck_resource(resource)) == NULL ) {
        info("bad resource id: %d, from process pid: %u", resource, pid);
		dlmd_reply_error(fd, DLMD_REPLY_BAD_RESOURCE);
		return;
	}
    lock_link_proc_res(proc, res);
    if (lock_trylock(proc, res, lock)) {
        lock_add_lock(proc, res, lock);
		dlmd_reply_ok(fd);
	} else {
		dlmd_reply_ne(fd);
	}
}
void dlmd_trylock(pid_t pid, resource_id_t resource, lock_type_t type)
{
	debug2("request from %u: trylock resource: %d lock type: %l", pid, resource, type);
	struct process *proc;
    int fd;
    if ((proc = lock_ck_process(pid)) == NULL) {
        proc = lock_add_process(pid);
        info("new process, pid %u", pid);
    }
    fd = proc->fd;
	struct resource *res;
	if ((res = lock_ck_resource(resource)) == NULL) {
		info("bad resource id: %d, from process pid: %u", resource, pid);
		dlmd_reply_error(fd, DLMD_REPLY_BAD_RESOURCE);
		return;
	}
    if (lock_trylock(proc, res, type) == NULL)
		dlmd_reply_ok(fd);
	else
		dlmd_reply_ne(fd);
}
void dlmd_unlock(pid_t pid, resource_id_t resource)
{
	debug2("request from %u: unlock resource: %s", pid, resource);
	int fd;
	struct process *proc;
	if ((proc = lock_ck_process(pid)) == NULL) {
		fd = dlmd_reply_mkfifo(pid);
		dlmd_reply_error(fd, DLMD_REPLY_BAD_PROCESS);
		return;
	} else
		fd = proc->fd;
	struct resource *res;
	if ((res = lock_ck_resource(resource)) == NULL ) {
		info("bad resource id: %d, from process pid: %u", resource, pid);
		dlmd_reply_error(fd, DLMD_REPLY_BAD_RESOURCE);
		return;
	}
	struct lock *lck;
	if ((lck = lock_ck_lock(res, proc)) == NULL) {
		dlmd_reply_error(fd, DLMD_REPLY_BAD_LOCK);
		return;
	}
	// TODO
	dlmd_reply_ok(fd);
}
